package cz.semjob.learning.instances.creator;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import cz.semjob.common.attribute.value.NominalStringAttributeValue;
import cz.semjob.document.AnnotatedDocument;
import cz.semjob.document.annotation.metadata.Entity;
import cz.semjob.document.processing.DocumentInstance;
import cz.semjob.document.processing.DocumentSentence;
import cz.semjob.document.processing.DocumentWord;
import cz.semjob.learning.data.TaxonomyLearningException;
import cz.semjob.learning.data.attribute.NumericInstanceAttribute;
import cz.semjob.learning.instances.LabeledTextInstance;
import cz.semjob.learning.instances.UnlabeledTextInstance;

@Component
public class LevelTextInstanceCreator extends BaseTextInstanceCreator implements
		IConfigurableTextInstanceCreator {

	private static Logger logger = Logger
			.getLogger(LevelTextInstanceCreator.class);

	public static final String CORRESPONDING_ACTIVITY = "CorrespondingActivity";
	public static final String CORRESPONDING_ACTIVITY_DISTANCE = "CorrespondingActivityDistance";

	public LevelTextInstanceCreator() {
		super();

		// attributesNamesList.add(CORRESPONDING_ACTIVITY_DISTANCE);
		// attributesNamesList.remove(HEAD_GENDER);
		// attributesNamesList.remove(SENTENCE_LENGTH);
		attributesNamesList.remove(PARAGRAPH_NUMBER);
		attributesNamesList.remove(HEAD_PROPER_NOUN);
		attributesNamesList.remove(IS_PART_OF_LIST);
		attributesNamesList.remove(IS_ITEM);

	}

	public void initTextInstanceCreator() {
		super.initTextInstanceCreator();
		attributesMap.put(CORRESPONDING_ACTIVITY_DISTANCE,
				new NumericInstanceAttribute(CORRESPONDING_ACTIVITY_DISTANCE));
		updateAttributes(attributesNamesList);
	}

	public LabeledTextInstance createOneLabeledInstance(
			AnnotatedDocument annotatedDocument, Entity entity,
			boolean positive, List<DocumentWord> words, Object... dataSources)
			throws TaxonomyLearningException {
		if (positive) {
			String wordsString = "";
			for (DocumentWord documentWord : words) {
				wordsString += documentWord.getText() + " ";
			}
			logger.debug("POSITIVE: " + wordsString);
		}
		LabeledTextInstance labeledTextInstance = super
				.createOneLabeledInstance(annotatedDocument, entity, positive,
						words);
		List<List<DocumentWord>> activityAnnotations = annotatedDocument
				.getPositiveAnnotations(annotationTypeFactory
						.getEntity("Activity"));
		createLevelAttributes(activityAnnotations, words, labeledTextInstance);
		return labeledTextInstance;
	}

	public UnlabeledTextInstance createOneUnlabeledInstance(
			DocumentInstance documentInstance, List<DocumentWord> pathWords,
			Object... dataSources) throws TaxonomyLearningException {
		UnlabeledTextInstance unlabeledTextInstance = super
				.createOneUnlabeledInstance(documentInstance, pathWords);
		List<List<DocumentWord>> activityAnnotations = null;
		if (attributesNamesList.contains(CORRESPONDING_ACTIVITY)) {
			Map<DocumentInstance, List<List<DocumentWord>>> activityInstances = (Map<DocumentInstance, List<List<DocumentWord>>>) dataSources[0];
			activityAnnotations = activityInstances.get(documentInstance);
		}
		createLevelAttributes(activityAnnotations, pathWords,
				unlabeledTextInstance);

		return unlabeledTextInstance;
	}

	// TODO refaktor
	private void createLevelAttributes(
			List<List<DocumentWord>> activityAnnotations,
			List<DocumentWord> words, UnlabeledTextInstance labeledTextInstance)
			throws TaxonomyLearningException {

		if (attributesNamesList.contains(CORRESPONDING_ACTIVITY)) {
			if (getCorrenpondingActivityDistance(words, activityAnnotations) > 0) {
				labeledTextInstance.addAttributeValue(CORRESPONDING_ACTIVITY,
						new NominalStringAttributeValue("", "yes",
								properNounAttribute));
			} else {
				labeledTextInstance.addAttributeValue(CORRESPONDING_ACTIVITY,
						new NominalStringAttributeValue("", "no",
								properNounAttribute));
			}
		}
		if (attributesNamesList.contains(CORRESPONDING_ACTIVITY_DISTANCE)) {
			labeledTextInstance
					.addAttributeValue(
							CORRESPONDING_ACTIVITY_DISTANCE,
							getCorrenpondingActivityDistance(words,
									activityAnnotations));
		}
	}

	protected int getCorrenpondingActivityDistance(List<DocumentWord> words,
			List<List<DocumentWord>> activityAnnotations) {
		DocumentSentence annotationSentence = getAnnotationSentence(words);

		for (List<DocumentWord> activityAnnotation : activityAnnotations) {
			DocumentSentence activitySentecne = getAnnotationSentence(activityAnnotation);
			if (annotationSentence.equals(activitySentecne)) {
				// now check, if activity is related to our annotation
				// check only first word of each annotation
				return getDependentAnnotationsDistance(activityAnnotation,
						words);
			}

		}
		return -1;
	}

	public void setMaxInstanceWordLength(int length) {
		MAX_WORDS = length;

	}

	public void setAttributesList(List<String> attributeNames) {
		updateAttributes(attributeNames);
	}

}
